

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

import java.util.*;
import java.util.BitSet;

import org.example.MainMenu;
import redis.clients.jedis.Jedis;

public class MapEditor extends JFrame {
    private EditableMapPanel mapPanel;
    private JSpinner rowSpinner, colSpinner, carSpinner;
    // 1. 声明为成员变量
    private JComboBox<String> algorithmComboBox;

    // 添加带参数的构造函数
    public MapEditor() {
        initEditorUI();
    }

    private void initEditorUI() {
        setTitle("自定义地图探索");
        setSize(800, 800);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout(5, 5));

        JPanel controlPanel = new JPanel();
        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));
        controlPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 尺寸设置面板
        JPanel sizePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        sizePanel.add(new JLabel("行数:"));
        rowSpinner = new JSpinner(new SpinnerNumberModel(10, 1, 500, 1));
        sizePanel.add(rowSpinner);

        sizePanel.add(new JLabel("列数:"));
        colSpinner = new JSpinner(new SpinnerNumberModel(10, 1, 500, 1));
        sizePanel.add(colSpinner);

        JButton sizeBtn = new JButton("应用尺寸");
        sizeBtn.addActionListener(this::handleResize);
        sizePanel.add(sizeBtn);

        // 小车设置面板
        JPanel carPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        carPanel.add(new JLabel("小车数量:"));
        carSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 20, 1));
        carPanel.add(carSpinner);

        JButton saveBtn = new JButton("载入地图");
        saveBtn.addActionListener(this::saveToRedis);
        carPanel.add(saveBtn);

        // 添加开始探索按钮
        JButton exploreBtn = new JButton("开始探索");
        exploreBtn.addActionListener(e -> startRealTimeMap());
        carPanel.add(exploreBtn);

        // 障碍物设置面板
        JPanel obstaclePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        obstaclePanel.add(new JLabel("障碍物数量:"));
        JSpinner obsSpinner = new JSpinner(new SpinnerNumberModel(10, 0, 10000, 1));
        obstaclePanel.add(obsSpinner);

        JButton randomObsBtn = new JButton("随机添加");
        randomObsBtn.addActionListener(e -> {
            int count = (Integer) obsSpinner.getValue();
            mapPanel.randomizeObstacles(count);
        });
        obstaclePanel.add(randomObsBtn);

        // === 新增：算法选择面板 ===
        JPanel algPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        algPanel.add(new JLabel("路径规划算法:"));
        algorithmComboBox = new JComboBox<>(new String[]{"A*", "AA*","BFS"});
        algorithmComboBox.setSelectedIndex(0); // 默认选择A*
        algPanel.add(algorithmComboBox);

        // 导航面板
        JPanel navPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JButton backBtn = new JButton("返回主菜单");
        backBtn.addActionListener(e -> {
            new MainMenu().setVisible(true);
            dispose();
        });
        navPanel.add(backBtn);

        // 添加到控制面板
        controlPanel.add(sizePanel);
        controlPanel.add(Box.createVerticalStrut(10));
        controlPanel.add(carPanel);
        controlPanel.add(Box.createVerticalStrut(10));
        controlPanel.add(obstaclePanel);
        controlPanel.add(Box.createVerticalStrut(10));
        controlPanel.add(navPanel);
        controlPanel.add(Box.createVerticalStrut(10));
        controlPanel.add(algPanel);

        mapPanel = new EditableMapPanel(10, 10);
        add(controlPanel, BorderLayout.NORTH);
        add(new JScrollPane(mapPanel), BorderLayout.CENTER);
    }

    private void startRealTimeMap() {
       // new RealTimeMapFrame().setVisible(true);
    }

    private void handleResize(ActionEvent e) {
        int newRows = (Integer) rowSpinner.getValue();
        int newCols = (Integer) colSpinner.getValue();
        mapPanel.updateGrid(newRows, newCols);
    }

    private void saveToRedis(ActionEvent e) {
        String mapName = "map"; // 直接使用默认地图名称 "map"
        int carCount = (Integer) carSpinner.getValue();
        new MapSaver(mapName, carCount).execute();
    }

    private class MapSaver extends SwingWorker<Void, Void> {
        private final String mapName;
        private final int carCount;
        private final String algorithm; // 存储算法名称

        public MapSaver(String mapName, int carCount) {
            this.mapName = mapName;
            this.carCount = carCount;
            this.algorithm = (String) algorithmComboBox.getSelectedItem();
        }

        @Override
        protected Void doInBackground() {
            try (Jedis jedis = new Jedis("localhost", 6379)) {
                // 获取地图数据
                int rows = mapPanel.getRows();
                int cols = mapPanel.getCols();
                BitSet obstacles = mapPanel.getObstacleBits();

                // 存储基础信息
                jedis.set("mapwidth", String.valueOf(cols));
                jedis.set("mapheight", String.valueOf(rows));
                // 存储算法到Redis ===
                jedis.set("map:alg", algorithm);

                // 生成小车位置
                Map<String, String> carPositions = generateCarPositions(rows, cols, obstacles, carCount);

                // 初始化视野数据
                BitSet lightBits = new BitSet(rows * cols);
                initializeLightData(lightBits, carPositions, rows, cols);

                // 存储到Redis
                storeRedisData(jedis, rows, cols, obstacles, lightBits, carPositions);

                SwingUtilities.invokeLater(() ->
                        JOptionPane.showMessageDialog(MapEditor.this,
                                "数据保存成功！\n" +
                                        "地图尺寸：" + cols + "x" + rows + "\n" +
                                        "小车位置：" + carPositions + "\n" +
                                        "初始点亮区域：" + formatLightBits(lightBits, rows, cols))
                );
            } catch (Exception ex) {
                ex.printStackTrace();
                SwingUtilities.invokeLater(() ->
                        JOptionPane.showMessageDialog(MapEditor.this, "错误：" + ex.getMessage())
                );
            }
            return null;
        }

        private void initializeLightData(BitSet lightBits, Map<String, String> carPositions,
                                         int rows, int cols) {
            // 遍历所有小车位置
            for (String position : carPositions.values()) {
                String[] coord = position.split(",");
                int x = Integer.parseInt(coord[0]);
                int y = Integer.parseInt(coord[1]);
                updateLightAroundCar(lightBits, x, y, rows, cols);
            }
        }


        private void updateLightAroundCar(BitSet lightBits, int x, int y,
                                          int rows, int cols) {
            for (int dy = -1; dy <= 1; dy++) {
                for (int dx = -1; dx <= 1; dx++) {
                    int nx = x + dx;
                    int ny = y + dy;

                    // 检查边界
                    if (nx >= 0 && nx < cols && ny >= 0 && ny < rows) {
                        int index = ny * cols + nx;
                        lightBits.set(index);
                    }
                }
            }
        }

        private void storeRedisData(Jedis jedis, int rows, int cols, BitSet obstacles,
                                    BitSet lightBits, Map<String, String> carPositions) {

            // 清除旧的小车位置数据
            for (int i = 1; i <= 10; i++) { // 假设最大小车数量为10
                String key = "car:" + i + ":position";
                if (jedis.exists(key)) {
                    jedis.del(key);
                }
            }

            // 存储障碍物（字符串格式）
            String obstacleData = RedisUtils.bitSetToString(obstacles, rows, cols);
            jedis.set("map:obstacle", obstacleData);

            // 存储视野数据（字符串格式）
            String lightData = RedisUtils.bitSetToString(lightBits, rows, cols);
            jedis.set("map:light", lightData);

            // 存储小车位置
            for (Map.Entry<String, String> entry : carPositions.entrySet()) {
                String carId = entry.getKey().replace("car", "");
                String[] coordinates = entry.getValue().split(",");
                jedis.hset("car:" + carId + ":position",
                        new HashMap<String, String>() {{
                            put("x", coordinates[0]);
                            put("y", coordinates[1]);
                        }}
                );
            }
            //存储小车数量
            jedis.set("carcount", String.valueOf(carCount));
        }

        private String formatLightBits(BitSet bits, int rows, int cols) {
            return RedisUtils.formatBitSet(bits, rows, cols);
        }
    }
    private Map<String, String> generateCarPositions(int rows, int cols,
                                                     BitSet obstacles, int count) {
        Map<String, String> cars = new LinkedHashMap<>();
        ArrayList<Point> available = new ArrayList<>();

        // 收集可用位置
        for (int y = 0; y < rows; y++) {
            for (int x = 0; x < cols; x++) {
                int index = y * cols + x;
                if (!obstacles.get(index)) {
                    available.add(new Point(x, y));
                }
            }
        }

        // 验证空间
        if (available.size() < count) {
            throw new RuntimeException("需要" + count + "个位置，但只有" + available.size() + "个可用");
        }

        // 随机选择位置
        Collections.shuffle(available);
        for (int i = 0; i < count; i++) {
            Point p = available.get(i);
            cars.put("car" + (i+1), p.x + "," + p.y);
        }
        return cars;
    }
}
